package com.gqzm.side.common.component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.gqzm.side.common.result.BizException;
import com.gqzm.side.common.result.ErrorCode;
import com.gqzm.side.common.result.Result;
import com.gqzm.side.common.result.VoidResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @ClassName: {@link RestRequest}
 * @description: 封装http rest请求
 * @author: peter qin
 * @date: 2023 11 21
 * @version: 1.0
 **/
@Slf4j
@Component
public class RestRequest {
    @Resource
    private RestTemplate restTemplate;

    public <R, P> R restCall(HttpMethod hm,
                             String url,
                             P param,
                             Class<R> clazz) {
        HttpHeaders hh = new HttpHeaders();
        hh.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<P> he = new HttpEntity<>(param, hh);
        ResponseEntity<String> result = restTemplate.exchange(url, hm, he, String.class);
        if (clazz != null) {
            return JSON.parseObject(result.getBody(), clazz);
        }
        return null;
    }

    public <R, P> R restCallTypeRef(HttpMethod hm,
                                    String url,
                                    P param,
                                    R clazz) {
        String body = this.basicTypeRef(hm, url, param, clazz);
        Objects.requireNonNull(body, "请求响应不能为空!");
        TypeReference<Result<R>> tr = new TypeReference<Result<R>>() {
        };
        Result<R> rd = JSON.parseObject(body, tr);
        this.checkSuccess(
                rd::getErrorCode,
                rd::getMessage
        );
        return rd.getData();
    }

    public <R, P> List<R> restCallTypeRefList(HttpMethod hm,
                                              String url,
                                              P param,
                                              Class<R> clazz) {
        String body = this.basicTypeRef(hm, url, param, clazz);
        Objects.requireNonNull(body, "请求响应不能为空!");
        JSONObject rd = JSON.parseObject(body);
        this.checkSuccess(
                () -> rd.getString("error_code"),
                () -> rd.getString("message")
        );
        JSONArray array = rd.getJSONArray("data");
        if (array == null || array.isEmpty()) {
            return Lists.newArrayList();
        }
        return array.toJavaList(clazz);
    }


    private <R, P> String basicTypeRef(HttpMethod hm,
                                       String url,
                                       P param,
                                       R clazz) {
        HttpHeaders hh = new HttpHeaders();
        hh.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<P> he = new HttpEntity<>(param, hh);
        ResponseEntity<String> result = restTemplate.exchange(
                url,
                hm,
                he,
                String.class);
        Objects.requireNonNull(result.getBody(), "请求响应不能为空!");
        if (clazz == null) {
            VoidResult vr = JSON.parseObject(
                    result.getBody(),
                    VoidResult.class);
            this.checkSuccess(
                    vr::getErrorCode,
                    vr::getMessage
            );
            return null;
        }
        return result.getBody();
    }


    private void checkSuccess(Supplier<String> errCode,
                              Supplier<String> message) {
        String ec = errCode.get();
        String msg = message.get();
        if (!StringUtils.equals(ec,
                ErrorCode.SUCCESS.getErrorCode())) {
            throw BizException.of(
                    ec,
                    msg
            );
        }
    }


    public void uploadFile(String code,
                           String fp,
                           String url,
                           String detectType,
                           String time,
                           Double score) {
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        HttpHeaders hh = new HttpHeaders();
        hh.setContentType(MediaType.MULTIPART_FORM_DATA);
        param.add("file", new FileSystemResource(fp));
        param.add("detect_type", detectType);
        param.add("time", time);
        param.add("score", score);
        param.add("code", code);
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(param, hh);
        String result = restTemplate.postForObject(
                url,
                entity,
                String.class
        );
        log.info("上传结果图片: {} 返回：{}", fp, result);
    }
}
